'''
代聪聪
Kerberos认证test__客户端
==========================================================
2022.5.7 登录和注册
2022.5.8 修改信息界面、登陆之后多线程开启
多线程部分很混乱
2022.5.10
修改注册部分的连接
修改 修改信息部分的连接
2022.5.12
客户端的注册、登录、修改的发送和接收报文的加密过程与解密过程修改完善
长报文用mysocket接收
==========================================================
'''
# import sys
import tkinter as tk
import tkinter.messagebox
from tkinter import *
from tkinter import ttk
import socket
import threading

import des2
import hash
from packet import get_pack  # 用来打包
from packet import pack  # 用来解析报文
import time
import config
import mysocket

k_c = "333"  # 登陆密码
k_c_hash = hash.encrypt(k_c)
print("kc_hash", type(k_c_hash), k_c_hash)
# sys.path.append('..')
# import hash
# from network-security import hash
# 修改

'''if id == '111' and password == '111':
    tk.messagebox.showinfo(title='welcome', message='欢迎您')'''
'''#  ===============================================================
#  用户类
#  ==============================================================='''
'''
class Customer:
    def __init__(self, id:str , password:str, name:str, sex:str, address:str, phone:int, money=0):
        self.id = id
        self.password = password
        self.name = name
        self.sex = sex
        self.address = address
        self.phone = phone
        self.money = money
c1 = Customer  # 实例化客户类'''

'''id = ''   # 用户ID
password = ''   # 登陆密码
name = ''   # 用户姓名
sex = ''    # 用户性别
address = ''   # 用户地址
phone = ''   # 用户电话号码
money = 0  # 用户余额'''

'''    # 注册
    def signature(self, password:str, name:str, sex:str, address:str, phone:str, money: 0):
        #  连接AS服务器将id与密码发送给AS
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        host = ""
        port = 8080
        buffer_size = 1024
        address = (host, port)
        # 开始连接AS服务器
        s.connect(address)
        if s is None:
            tk.messagebox.showinfo(title='错误', message='无法连接到AS服务器')
        else:'''

id_tgs = 123456
# from matplotlib import table
#  ===============================================================
#  主界面
#  ===============================================================
#  根窗口

main_win = tk.Tk()
main_win.title('用户点餐系统')
main_win.geometry('800x500')
main_win.withdraw()  # 隐藏

'''tk.Label(main_win, text='用户名:').place(x=20, y=20)
tk.Label(main_win, text='余  额:').place(x=60, y=20)'''

#  ===============================================================
#  登陆界面
#  ===============================================================
#  登录窗口

login_win = tk.Toplevel(main_win)  # 在主界面的上层显示
login_win.title('客户登录')
login_win.geometry('350x350+300+300')

#  登录：用户id、密码  在最外层  _lg代表登陆时的用户输入
tk.Label(login_win, text='用户ID').place(x=60, y=100)
id_lg = tk.Entry(login_win)
id_lg.place(x=130, y=100)

tk.Label(login_win, text='密  码').place(x=60, y=150)
password_lg = tk.Entry(login_win, show='*')
password_lg.place(x=130, y=150)


# 登录按钮实现，也在最外层
def log():
    id1 = id_lg.get()
    password1 = password_lg.get()
    password1_en = hash.encrypt(password1)
    # 连接AS服务器获取tgt
    s_as = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    '''addr_as = "127.0.0.1"
    port_as = 10001'''
    buffer_size = 1024
    address_as = (config.addr_as, config.port_as)

    # 开始连接AS服务器
    s_as.connect(address_as)
    while True:
        ts1 = time.time()
        info2as = {"idc": id1, "passwd": password1_en, "id_tgs": 'tgs', "ts1": ts1}
        print(type(password1_en), password1_en)
        # msg2as = get_pack('c_a', 'user', 'get_ticket1', content=str(info2as))  # 改成str
        msg2as = get_pack('c_a', 'user', 'get_ticket1', content=str(info2as))  # 改成str
        # a = pack(msg2as)
        print('msg', len(msg2as), msg2as)
        print(str(info2as))
        s_as.send(msg2as)
        # msg2as_re = pack(s_as.recv(10240))
        # print(msg2as_re)
        # msg2as_re = pack(s_as.recv(10240))  # 接收AS服务器端发来的消息
        """
        cnt = 0
        while True:
            a = s_as.recv(2048)
            cnt += 1
            print(">>", cnt, "---", pack(a).content)
        """
        msg2as_re = mysocket.recv(s_as)
        # print('recv到了')
        print('接收到AS的消息', len(msg2as_re.content), type(msg2as_re.content), msg2as_re.content)
        print('password1_en(client1的密钥): ', type(password1_en), password1_en)
        content_plain = des2.decrypt(msg2as_re.content, password1_en)
        # print(msg2as_re.content)
        # print('>>>111:', type(k_c_hash), k_c_hash)
        # _content1 = dict(eval(msg2as_re.content))  # 没有拆
        # _text1 = _content1["tgt"]
        # text1 = dict(eval(des2.decrypt(str(_content1), k_c_hash)))
        print('解密后:', type(content_plain), content_plain)
        content_dic = dict(eval(content_plain))
        tgt = content_dic['tgt']
        if tgt is not None:
            tk.messagebox.showinfo(title='成功', message='请求AS认证成功')
            break
        else:
            tk.messagebox.showinfo(title='错误', message='请求AS认证失败')
    # kc_tgs = text["kc_tgs"]
    s_as.close()  # 关闭socket
    print('as认证结束')

    #  用tgt向TGS服务器获取st
    s_tgs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    address_tgs = (config.addr_tgs, config.port_tgs)
    #  开始连接TGS服务器
    s_tgs.connect(address_tgs)
    while True:
        kc_tgs = int(content_dic["kc_tgs"])
        ts3 = time.time()
        lifetime = '480'
        authenticator = {"idc": id1, "ad_c": '', "ts_3": ts3, "Lifetime": lifetime}
        authenticator_c = des2.encrypt(str(authenticator), kc_tgs)
        info2tgs = {"idv": '', "tgt": tgt, "Authenticator_c": authenticator_c}
        msg2tgs = get_pack('c_t', 'user', 'request_ticket2', content=str(info2tgs))  # 这里C向TGS发送的消息
        mysocket.send(s_tgs, msg2tgs)
        # s_tgs.(msg2tgs)
        print('发给tgs的消息：', type(str(info2tgs)), str(info2tgs))
        # msg2tgs_re = pack(s_tgs.recv(buffer_size))  # 接收TGS发送回来的票据st
        # msg2tgs_re = s_tgs.recv(buffer_size)  # 接收TGS发送回来的票据st
        msg2tgs_re = mysocket.recv(s_tgs)
        # print('未解密', type(msg2tgs_re.content), len(msg2tgs_re.content), msg2tgs_re.content)
        print('密钥', type(kc_tgs), kc_tgs)
        content2_plain = des2.decrypt(msg2tgs_re.content, kc_tgs)
        content2_dic = dict(eval(content2_plain))
        # _text2 = _content2content2_dic
        # text2 = dict(eval(des2.decrypt(str(_content2), kc_tgs)))
        st = content2_dic["ticket"]
        # print("ticket", st)
        # kc_v = text2[""]
        if st is not None:
            tk.messagebox.showinfo(title='成功', message='请求TGS票据成功')
            break
        else:
            tk.messagebox.showinfo(title='错误', message='请求TGS票据失败')
            break
    s_tgs.close()

    #  用st向V请求登录
    s_ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    address_ss = (config.addr_ss, config.port_ss_client)
    # 开始连接SS服务器
    s_ss.connect(address_ss)
    # ticket = text2["ticket"]
    while True:

        kc_v = int(content2_dic['kc_v'])  # 强制类型转换成了int
        private_key_ss = str(content2_dic["private_key"])
        print(">>获取到私钥", type(private_key_ss), private_key_ss)
        ts5 = time.time()
        _authenticator2s = {"id_c": id1, "ad_c": '', "ts_5": ts5}
        authenticator2s = des2.encrypt(str(_authenticator2s), kc_v)
        info2ss = {"ticket": st, "Authenticator_c": authenticator2s}
        msg2ss = get_pack('c_s', sign='user', control_type='message5', content=str(info2ss))
        print('发送给ss的消息',len(msg2ss),msg2ss)
        mysocket.send(s_ss, msg2ss)  # 分片发送
        # msg2ss_re = pack(s_ss.recv(buffer_size))
        # _content3 = dict(eval(msg2ss_re.content))
        msg2ss_re = mysocket.recv(s_ss)  # 分片接收
        _content3 = des2.decrypt(msg2ss_re.content, kc_v)
        content3_dic = dict(eval(_content3))
        ts6 = content3_dic['ts6']
        pk_v = content3_dic['pk_v']
        print('pk_v: ', type(pk_v), pk_v)
        if ts6 == ts5 + 1:
            tk.messagebox.showinfo(title='成功', message='登录成功')
            # s_ss.close()


            #
            # mysocket.flush(s_ss)
            # test_msg_recv_pack = mysocket.recv(s_ss)
            # print("数字签名验证成功！！！")
            # test_msg_recv_pack = mysocket.recv(s_ss,sessionkey=kc_v, publickey=pk_v)

            # print("收到的原文：",test_msg_recv)
            # test_msg_recv_pack = pack(test_msg_recv,sessionkey=kc_v,publickey=pk_v)
            # print("验证数字签名输出content:",test_msg_recv_pack)

            # print("调试数字签名A", test_msg_recv)
            # test_msg_recv = mysocket.recv(s_ss)
            # test_msg =
            # mysocket.send(s_ss, test_msg)
            break
        else:
            tk.messagebox.showinfo(title='失败', message='登录失败')

    '''
    
    '''

    '''def recv():
        msg = s_ss.recv(1024)  # 接收来自服务器的消息
        # 对接收到的报文解析并输出(到控件)
        print(msg.decode('utf-8'))'''
    '''#  开启多线程
    new_sock, add = s_ss.accept()
    threading.Thread(target=recv(), args=(new_sock,)).start()'''
    # s_ss.close()
    login_win.withdraw()  # 隐藏登录页面
    main_win.deiconify()  # 显示主界面

    def modify_info():

        mod_win = tk.Toplevel(main_win)
        mod_win.geometry('300x300+200+200')
        mod_win.title('用户管理界面')

        #  输入框，获得修改信息
        tk.Label(mod_win, text='ID(不可更改)').place(x=20, y=20)
        tk.Label(mod_win, text=id1).place(x=100, y=20)

        tk.Label(mod_win, text='修改姓名').place(x=20, y=65)
        name_md = tk.Entry(mod_win)
        name_md.place(x=100, y=65)

        tk.Label(mod_win, text='修改性别').place(x=20, y=110)
        sex_md = tk.Entry(mod_win)
        sex_md.place(x=100, y=110)

        tk.Label(mod_win, text='修改地址').place(x=20, y=165)
        ad_md = tk.Entry(mod_win)
        ad_md.place(x=100, y=165)

        tk.Label(mod_win, text='修改号码').place(x=20, y=210)
        tp_md = tk.Entry(mod_win)
        tp_md.place(x=100, y=210)

        def ok_mod():

            name_m = name_md.get()
            sex_m = sex_md.get()
            ad_m = ad_md.get()
            tp_m = tp_md.get()

            mdinfo_req = {"id": id1, "name": name_m, "sex": sex_m, "address": ad_m, "phonenumber": tp_m}
            mypacket = get_pack('c_s', 'user', 'modify_info', content=str(mdinfo_req),
                                sessionkey=kc_v, privatekey=private_key_ss)
            mysocket.send(s_ss,mypacket)
            mdinfo_re = mysocket.recv(s_ss, sessionkey=kc_v, publickey=pk_v)
            if int(mdinfo_re.state) != 1:
                tk.messagebox.showinfo(title='错误', message='信息修改失败')
            else:
                tk.messagebox.showinfo(title='成功', message='信息修改成功')

                mod_win.destroy()  # 销毁修改信息页面

        # 确定按钮
        tk.Button(mod_win, text='确定修改', command=ok_mod).place(x=100, y=250)

    def recharge():
        # 余额提现界面
        out_win = tk.Toplevel(main_win)
        out_win.title('充值')
        out_win.geometry('300x150+200+200')

        #  输入框
        tk.Label(out_win, text='密码').place(x=20, y=20)
        pwd_co = tk.Entry(out_win)
        pwd_co.place(x=100, y=20)

        tk.Label(out_win, text='充值金额').place(x=20, y=80)
        money_co = tk.Entry(out_win)
        money_co.place(x=100, y=80)

        def ok_cash():
            pwd_o = pwd_co.get()
            money_o = money_co.get()

            out_req = {"id": id1, "passwd": pwd_o, "money": money_o}
            mypacket = get_pack('c_s', 'user', 'cash_out', content=str(out_req), sessionkey=kc_v,
                                privatekey=private_key_ss)
            mysocket.send(s_ss, mypacket)
            out_re = mysocket.recv(s_ss, sessionkey=kc_v, publickey=pk_v)
            if int(out_re.state) != 1:
                tk.messagebox.showinfo(title='错误', message='充值失败')
            else:
                tk.messagebox.showinfo(title='成功', message='充值成功')

                out_win.destroy()

        tk.Button(out_win, text='确定充值', command=ok_cash).place(x=100, y=120)

    # 布置按钮
    tk.Button(main_win, text='修改信息', command=modify_info).place(x=420, y=20)
    tk.Button(main_win, text='充值', command=recharge).place(x=420, y=60)

#  ===============================================================
#  注册界面
#  ===============================================================

'''
注册界面是由按钮“注册”唤醒的
所以注册相关全部打包在一个函数里面
'''


def reg():
    #  注册窗口
    reg_win = tk.Toplevel(login_win)
    reg_win.title('用户注册界面')
    reg_win.geometry('300x350+200+200')

    #  输入框 获取用户详细信息
    tk.Label(reg_win, text='用户ID').place(x=30, y=20)
    id_rg = tk.Entry(reg_win)
    id_rg.place(x=100, y=20)

    tk.Label(reg_win, text='用户密码').place(x=30, y=65)
    password_rg = tk.Entry(reg_win, show='*')
    password_rg.place(x=100, y=65)

    tk.Label(reg_win, text='用户名').place(x=30, y=110)
    name_rg = tk.Entry(reg_win)
    name_rg.place(x=100, y=110)

    tk.Label(reg_win, text='用户性别').place(x=30, y=155)
    sex_rg = tk.Entry(reg_win)
    sex_rg.place(x=100, y=155)

    tk.Label(reg_win, text='用户地址').place(x=30, y=200)
    address_rg = tk.Entry(reg_win)
    address_rg.place(x=100, y=200)

    tk.Label(reg_win, text='用户号码').place(x=30, y=245)
    phone_rg = tk.Entry(reg_win)
    phone_rg.place(x=100, y=245)

    def ok_reg():
        # 获得用户输入 _rg代表注册时的输入信息
        id2 = id_rg.get()
        password2 = password_rg.get()
        pwd2_en = hash.encrypt(password2)
        name2 = name_rg.get()
        sex2 = sex_rg.get()
        address2 = address_rg.get()
        phone2 = phone_rg.get()

        # 触发功能按钮

        # 创建socket准备连接AS
        s_as = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        buffer_size = 1024
        address_as = (config.addr_as, config.port_as)
        # 开始连接AS服务器
        s_as.connect(address_as)
        print(address_as)
        while True:
            info2as = {"id": id2, "passwd": pwd2_en}
            msg2as = get_pack('c_a', 'user', 'request_enroll', content=str(info2as))  # 请求注册的消息
            s_as.send(msg2as)
            flag_as = s_as.recv(buffer_size)
            print(flag_as)
            msg2as_re = pack(flag_as)
            print(msg2as_re.state)
            if int(msg2as_re.state) != 1:
                tk.messagebox.showinfo(title='错误', message='AS注册失败')
            else:
                tk.messagebox.showinfo(title='成功', message='AS注册成功')
                break
        s_as.close()  # 关闭与AS通信的socket

        # 创建socket准备连接SS
        s_ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        address_ss = (config.addr_ss, config.port_ss_client)
        # 开始连接SS服务器
        s_ss.connect(address_ss)
        while True:
            info2ss = {"id": id2, "passwd": pwd2_en, "name": name2, "sex": sex2, "address": address2,
                       "phonenumber": phone2}
            msg2ss = get_pack('c_s', 'user', 'signature', content=str(info2ss))  # 请求注册的消息
            print(msg2ss)
            s_ss.send(msg2ss)
            flag_ss = s_ss.recv(1024)
            print(flag_ss)
            msg2ss_re = pack(flag_ss)
            if int(msg2ss_re.state) != 1:
                tk.messagebox.showinfo(title='错误', message='SS注册失败')
            else:
                tk.messagebox.showinfo(title='成功', message='SS注册成功')
                break
        # print('yes')
        s_ss.close()  # 关闭与SS通信的socket

        #  注册成功,摧毁注册界面
        reg_win.destroy()

    # 按钮布置：确定，唤起功能按钮
    tk.Button(reg_win, text='确定', command=ok_reg).place(x=245, y=300)


#  ===============================================================
#  修改信息界面
#  ===============================================================


def alt():
    alt_win = tk.Toplevel(login_win)
    alt_win.title('修改用户信息')
    alt_win.geometry('300x300+200+200')

    #  输入框， 输入旧密码和新密码，
    tk.Label(alt_win, text='ID(不可更改)').place(x=25, y=20)
    id_alt = tk.Entry(alt_win)
    id_alt.place(x=100, y=20)

    tk.Label(alt_win, text='旧密码').place(x=25, y=65)
    password_alt = tk.Entry(alt_win)
    password_alt.place(x=100, y=65)

    tk.Label(alt_win, text='新密码').place(x=25, y=110)
    re_pwd_alt = tk.Entry(alt_win)
    re_pwd_alt.place(x=100, y=110)

    '''tk.Label(alt_win, text='姓名').place(x=25, y=155)
    name_alt = tk.Entry(alt_win)
    name_alt.place(x=100, y=155)

    tk.Label(alt_win, text='性别').place(x=25, y=200)
    sex_alt = tk.Entry(alt_win)
    sex_alt.place(x=100, y=200)

    tk.Label(alt_win, text='电话').place(x=25, y=245)
    phone_alt = tk.Entry(alt_win)
    phone_alt.place(x=100, y=245)

    tk.Label(alt_win, text='地址').place(x=25, y=290)
    address_alt = tk.Entry(alt_win)
    address_alt.place(x=100, y=290)'''

    def ok_alt():

        # 获取用户输入 re_ 为修改后的信息
        id3 = id_alt.get()
        pwd3 = password_alt.get()
        pwd3_en = hash.encrypt(pwd3)  # hash加密后的密码
        print('pwd3_en', type(pwd3_en), pwd3_en)
        re_pwd = re_pwd_alt.get()
        re_pwd_en = hash.encrypt(re_pwd)
        print('re_pwd_en', type(re_pwd_en), re_pwd_en)
        '''re_name = name_alt.get()
        re_sex = sex_alt.get()
        re_phone = phone_alt.get()
        re_addr = address_alt.get()'''

        # 触发功能按钮

        # 创建socket准备连接AS
        s_as = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        '''addr_as = "127.0.0.1"
        port_as = 10001'''
        buffer_size = 1024
        address_as = (config.addr_as, config.port_as)
        # 开始连接AS服务器
        s_as.connect(address_as)
        while True:
            info2as = {"id": id3, "passwd_old": pwd3_en, "passwd_new": re_pwd_en}
            msg2as = get_pack('c_a', 'user', 'modify_pwd', content=str(info2as))  # 请求修改的消息
            s_as.send(msg2as)
            flag_as = s_as.recv(buffer_size)
            msg_re = pack(flag_as)
            if int(msg_re.state) != 1:
                tk.messagebox.showinfo(title='错误', message='AS信息更改失败')

            else:
                tk.messagebox.showinfo(title='成功', message='AS信息更改成功')
                break
        s_as.close()  # 关闭与AS通信的socket

        # 创建socket准备连接SS
        s_ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        '''addr_ss = "172.27.76.36"
        port_ss = 6969'''
        address_ss = (config.addr_ss, config.port_ss_client)
        # 开始连接SS服务器
        s_ss.connect(address_ss)
        while True:
            info2ss = {"id": id3, "passwd_old": pwd3_en, "passwd_new": re_pwd_en}
            msg2ss = get_pack('c_s', 'user', 'modify_pwd', content=str(info2ss))  # 请求修改的消息
            s_ss.send(msg2ss)
            flag_ss = s_ss.recv(buffer_size)
            msg_re = pack(flag_ss)
            if int(msg_re.state) != 1:
                tk.messagebox.showinfo(title='错误', message='SS信息更改失败')
            else:
                tk.messagebox.showinfo(title='成功', message='SS信息更改成功')
                break

        s_ss.close()  # 关闭与SS通信的socket

        alt_win.destroy()  # 销毁修改信息窗口

    # 按钮布置，确定 唤起功能按钮
    tk.Button(alt_win, text='确定', command=ok_alt).place(x=240, y=250)


#  按钮布置：登录、注册、修改信息  在最外层
tk.Button(login_win, text='登录', command=log).place(x=80, y=200)
tk.Button(login_win, text='注册', command=reg).place(x=160, y=200)
tk.Button(login_win, text='修改密码', command=alt).place(x=240, y=200)


#  ===============================================================
#  报文界面
#  ===============================================================


def insert():
    info = [
        ['C-A', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx'],
        ['A-C', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx'],
        ['A-T', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx'],
        ['C-T', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx'],
        ['T-C', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx'],
        ['T-V', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx'],
        ['V-T', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx', 'xxx']
    ]
    for index, data in enumerate(info):
        table.insert('', END, values=data)  # 添加数据到末尾


def delete():
    obj = table.get_children()


#  界面
msg_win = tk.Tk()
msg_win.title('报文输出界面')
screenwidth = msg_win.winfo_screenwidth()
screenheight = msg_win.winfo_screenheight()
width = 1000
height = 500
# x = int((screenwidth - width) / 2)
# y = int((screenheight - height) / 2)
msg_win.geometry('1000x300+650+350')

columns = ['方向', '密文', '密文类型', '密文时间', '密文数据字段', '明文', '明文类型', '明文时间', '明文数据字段']
table = ttk.Treeview(
    master=msg_win,  # 父容器
    height=10,  # 表格显示的行数
    columns=columns,  # 显示的列
    show='headings',  # 隐藏首列
)
#  定义表头
table.heading(column='方向', text='方向', anchor='w', command=lambda: print('方向'))
table.heading('密文', text='密文', )
table.heading('密文类型', text='密文类型', )
table.heading('密文时间', text='密文时间', )
table.heading('密文数据字段', text='密文数据字段', )
table.heading('明文', text='明文', )
table.heading('明文类型', text='明文类型', )
table.heading('明文时间', text='明文时间', )
table.heading('明文数据字段', text='明文数据字段', )

#  定义列
table.column('方向', width=100, minwidth=100, anchor=S, )
table.column('密文', width=100, minwidth=100, anchor=S)
table.column('密文类型', width=100, minwidth=100, anchor=S)
table.column('密文时间', width=100, minwidth=100, anchor=S)
table.column('密文数据字段', width=100, minwidth=100, anchor=S)
table.column('明文', width=100, minwidth=100, anchor=S)
table.column('明文类型', width=100, minwidth=100, anchor=S)
table.column('明文时间', width=100, minwidth=100, anchor=S)
table.column('明文数据字段', width=100, minwidth=100, anchor=S)
table.pack(pady=20)

insert()
f = Frame(msg_win)
f.pack()
Button(f, text='刷新', bg='pink', width=20, command=insert).pack(side=LEFT)

#  运行
if __name__ == '__main__':
    main_win.mainloop()
